package jabachat;

import fonts.InternalFont;
import java.awt.Color;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.MalformedURLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import newDocument.MyEditorKit;

public class ChatGUI extends javax.swing.JFrame implements ChatUI {
    // TODO sendPost() отправляет все посты
    // TODO в чатклиенте флаг - подключён или нет

    Thread t;
    NullChatClient chat;
    String s = "body { background-color:#EEEEEE;  font-family: sans, Trebuchet MS; } a { color:#FF6600; } .reply {color:#FF6600;}";
    private HTMLEditorKit htmlKit;
    public HTMLDocument htmlDoc;
    BoundedRangeModel brm;
    private JPopupMenu postsTextPanePopup;
    private JPopupMenu replyTextAreaPopup;
    private String lastPost;

    /**
     * Creates new form chatGUI
     */
    public ChatGUI() {
        setLAF();
        initComponents();
        createPopups();

        postsTextPane.setMargin(null);
        brm = postsScrollPane.getVerticalScrollBar().getModel();
        htmlKit = new MyEditorKit();
        //htmlKit = new HTMLEditorKit();
        postsTextPane.setEditorKit(htmlKit);
        htmlDoc = (HTMLDocument) htmlKit.createDefaultDocument();
        postsTextPane.setDocument(htmlDoc);
        htmlKit.getStyleSheet().addRule(s);
        radioLabel.setVisible(false);
        //  htmlDoc.setDocumentFilter(new DocumentSizeFilter());

        setFonts();

//        try {
//            htmlKit.getStyleSheet().loadRules(new BufferedReader(new FileReader("d:\\style.css")), null);
//            //htmlDoc.getStyleSheet().loadRules(new BufferedReader(new FileReader("style.css")), null);
//        } catch (IOException ex) {
//
//        }

//        HyperlinkListener hyperlinkListener = new ActivatedHyperlinkListener();
//        postsTextPane.addHyperlinkListener(hyperlinkListener);
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSplitPane = new javax.swing.JSplitPane();
        postsScrollPane = new javax.swing.JScrollPane();
        postsTextPane = new javax.swing.JTextPane();
        replyPanel = new javax.swing.JPanel();
        sendButton = new javax.swing.JButton();
        replyScrollPane = new javax.swing.JScrollPane();
        replyTextArea = new javax.swing.JTextArea();
        onlineLabel = new javax.swing.JLabel();
        radioLabel = new javax.swing.JLabel();
        connectButton = new javax.swing.JToggleButton();
        HandshakeField = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        ChatField = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("jabaChat");

        jSplitPane.setDividerLocation(290);
        jSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane.setResizeWeight(0.5);
        jSplitPane.setDoubleBuffered(true);

        postsTextPane.setBorder(null);
        postsTextPane.setEditable(false);
        postsTextPane.setFont(postsTextPane.getFont());
        postsTextPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
            public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
                postsTextPaneHyperlinkUpdate(evt);
            }
        });
        postsScrollPane.setViewportView(postsTextPane);

        jSplitPane.setTopComponent(postsScrollPane);

        sendButton.setFont(new java.awt.Font("sansserif", 0, 14)); // NOI18N
        sendButton.setText("↵");
        sendButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                sendButtonMouseReleased(evt);
            }
        });

        replyScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        replyScrollPane.setAutoscrolls(true);

        replyTextArea.setColumns(1);
        replyTextArea.setFont(replyTextArea.getFont().deriveFont(replyTextArea.getFont().getSize()+5f));
        replyTextArea.setLineWrap(true);
        replyTextArea.setRows(1);
        replyTextArea.setWrapStyleWord(true);
        replyTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                replyTextAreaKeyReleased(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                replyTextAreaKeyTyped(evt);
            }
        });
        replyScrollPane.setViewportView(replyTextArea);

        javax.swing.GroupLayout replyPanelLayout = new javax.swing.GroupLayout(replyPanel);
        replyPanel.setLayout(replyPanelLayout);
        replyPanelLayout.setHorizontalGroup(
            replyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(replyPanelLayout.createSequentialGroup()
                .addComponent(replyScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 842, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(sendButton))
        );
        replyPanelLayout.setVerticalGroup(
            replyPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(replyScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 51, Short.MAX_VALUE)
            .addComponent(sendButton, javax.swing.GroupLayout.DEFAULT_SIZE, 56, Short.MAX_VALUE)
        );

        jSplitPane.setBottomComponent(replyPanel);

        onlineLabel.setText("Online:");

        radioLabel.setText("Radio:");

        connectButton.setText("Connect");
        connectButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                connectButtonMouseReleased(evt);
            }
        });

        HandshakeField.setText("127.0.0.1");

        jLabel1.setText("IP:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSplitPane)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(connectButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(radioLabel)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(HandshakeField, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(ChatField, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 392, Short.MAX_VALUE)
                        .addComponent(onlineLabel)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 352, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(connectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(radioLabel)
                    .addComponent(onlineLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(HandshakeField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1)
                    .addComponent(ChatField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void setLAF() {
        try {

            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            //     UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
            //  UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
            SwingUtilities.updateComponentTreeUI(this);
            pack();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    private void setFonts() {
        MutableAttributeSet attrs = postsTextPane.getInputAttributes();


        Font font = InternalFont.getFont(InternalFont.VERDANA, Font.PLAIN, 12);
        Font fontI = InternalFont.getFont(InternalFont.VERDANA_I, Font.PLAIN, 14);
        Font fontB = InternalFont.getFont(InternalFont.VERDANA_B, Font.PLAIN, 14);
        Font fontBI = InternalFont.getFont(InternalFont.VERDANA_BI, Font.PLAIN, 14);

        StyleConstants.setFontFamily(attrs, font.getFamily());
        StyleConstants.setFontSize(attrs, font.getSize());

        StyleConstants.setItalic(attrs, (fontI.getStyle() & Font.ITALIC) != 0);
        StyleConstants.setBold(attrs, (fontB.getStyle() & Font.BOLD) != 0);
        

        StyleConstants.setForeground(attrs, Color.BLACK);
        htmlDoc.setCharacterAttributes(0, htmlDoc.getLength() + 1, attrs, true);

        replyTextArea.setFont(font);
       postsTextPane.setFont(font);
    }

    private void createPopups() {
        postsTextPanePopup = new JPopupMenu();
        replyTextAreaPopup = new JPopupMenu();

        MouseAdapter copyMouseAdapter = new java.awt.event.MouseAdapter() {

            @Override
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                copyText(evt);
            }
        };

        MouseAdapter quoteMouseAdapter = new java.awt.event.MouseAdapter() {

            @Override
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                quoteText(evt);
            }
        };

        MouseAdapter pasteMouseAdapter = new java.awt.event.MouseAdapter() {

            @Override
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                pasteText();
            }
        };

        JMenuItem copyMenuItem = new JMenuItem("Copy");
        copyMenuItem.addMouseListener(copyMouseAdapter);

        JMenuItem quoteMenuItem = new JMenuItem("Quote");
        quoteMenuItem.addMouseListener(quoteMouseAdapter);

        postsTextPanePopup.add(copyMenuItem);
        postsTextPanePopup.add(quoteMenuItem);

        JMenuItem copyReplyMenuItem = new JMenuItem("Copy");
        copyReplyMenuItem.addMouseListener(copyMouseAdapter);

        JMenuItem quoteReplyMenuItem = new JMenuItem("Quote");
        quoteReplyMenuItem.addMouseListener(quoteMouseAdapter);

        JMenuItem pasteReplyMenuItem = new JMenuItem("Paste");
        pasteReplyMenuItem.addMouseListener(pasteMouseAdapter);

        replyTextAreaPopup.add(copyReplyMenuItem);
        replyTextAreaPopup.add(quoteReplyMenuItem);
        replyTextAreaPopup.add(pasteReplyMenuItem);

        MouseListener popupListener = new java.awt.event.MouseAdapter() {

            @Override
            public void mouseReleased(MouseEvent e) {
                maybeShowPopup(e);
            }

            @Override
            public void mousePressed(MouseEvent e) {
                maybeShowPopup(e);
            }

            private void maybeShowPopup(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    if (e.getComponent() == postsTextPane) {
                        postsTextPanePopup.show(e.getComponent(),
                                e.getX(), e.getY());
                    } else {
                        replyTextAreaPopup.show(e.getComponent(),
                                e.getX(), e.getY());
                    }

                }
            }
        };

        postsTextPane.addMouseListener(popupListener);
        replyTextArea.addMouseListener(popupListener);
    }

    private void copyText(java.awt.event.MouseEvent evt) {
        if (evt.getComponent().getParent() == postsTextPanePopup) {
            postsTextPane.copy();
        } else {
            replyTextArea.copy();
        }
    }

    private void quoteText(MouseEvent evt) {
        if (evt.getComponent().getParent() == postsTextPanePopup && postsTextPane.getSelectedText() != null) {
            replyTextArea.insert(" *> " + postsTextPane.getSelectedText() + "* ", replyTextArea.getCaretPosition());
        } else {
            if (replyTextArea.getSelectedText() != null) {
                replyTextArea.replaceSelection(" *> " + replyTextArea.getSelectedText() + "* ");
            } else { //if both text components haven't selected text than get it from clipboard
                Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                Transferable contents = systemClipboard.getContents(null);
                if ((contents != null) && contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                    try {
                        String result = (String) contents.getTransferData(DataFlavor.stringFlavor);
                        replyTextArea.insert(" *> " + result + "* ", replyTextArea.getCaretPosition());
                    } catch (Exception e) {
                        System.err.println(e);
                    }
                }
            }
        }
    }

    private void pasteText() {
        replyTextArea.paste();
    }

    @Override
    public void message(String reply, int type) {
        try {
            switch (type) {
                case 1: //post
                    boolean wasAtBottom = ((brm.getValue() + brm.getExtent()) == brm.getMaximum());
                    htmlKit.insertHTML((HTMLDocument) postsTextPane.getDocument(), htmlDoc.getLength(), processPost(reply), 1, 0, Tag.BODY);
                    if (wasAtBottom) {
                        //brm.setValue(brm.getMaximum());
                        postsTextPane.setCaretPosition(postsTextPane.getDocument().getLength());
                    }   //setFonts();
                    break;
                case 5: //captcha
                    htmlKit.insertHTML((HTMLDocument) postsTextPane.getDocument(), htmlDoc.getLength(), "<img src=" + reply + " /><br>", 1, 0, Tag.BODY);
                    break;
                case 4: //radio
                    radioLabel.setText("Radio: " + reply);
                    break;
                case 2: //online
                    onlineLabel.setText("Online: " + reply);
                    break;
                default: {
                    htmlKit.insertHTML((HTMLDocument) postsTextPane.getDocument(), htmlDoc.getLength(), reply, 1, 0, Tag.BODY);
                    break;
                }
            }
        } catch (Exception e) {
            System.err.println(e);
        }

    }
    private void replyTextAreaKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_replyTextAreaKeyReleased
        if (evt.isControlDown() && (evt.getKeyCode() == KeyEvent.VK_L)) {
            replyTextArea.insert(lastPost, replyTextArea.getCaretPosition());
        }
    }//GEN-LAST:event_replyTextAreaKeyReleased

    private void postsTextPaneHyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {//GEN-FIRST:event_postsTextPaneHyperlinkUpdate
        if (evt.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
            String url = evt.getURL().toString();
            if (url.startsWith("http://POST.NUM/")) {
                replyTextArea.insert(" >>" + url.substring(16) + " ", replyTextArea.getCaretPosition());
            } else {
                DefaultBrowser.browse(evt.getURL());
            }
        }
    }//GEN-LAST:event_postsTextPaneHyperlinkUpdate

    private void connectButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_connectButtonMouseReleased
        if (connectButton.isSelected()) {
            String hf = HandshakeField.getText();
            String cf = ChatField.getText();
            try {
                 chat = new NullChatClient(this, "http://"+hf, cf);
              //  chat = new NullChatClient(this, "http://0chan.ru/0chat", "0chan.ru");
                t = new Thread(chat);
                t.setDaemon(true);
                t.start();
            } catch (Exception e) {
                System.out.println(e.toString());
            }

        } else {
            chat.disconnect();
            htmlDoc = (HTMLDocument) htmlKit.createDefaultDocument();
            postsTextPane.setDocument(htmlDoc);
                    
        }
    }//GEN-LAST:event_connectButtonMouseReleased

    private void sendButtonMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_sendButtonMouseReleased
        sendPost();
    }//GEN-LAST:event_sendButtonMouseReleased

    private void replyTextAreaKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_replyTextAreaKeyTyped
        if (evt.getKeyChar() == KeyEvent.VK_ENTER) {
            sendPost();
        }
    }//GEN-LAST:event_replyTextAreaKeyTyped
    private void sendPost() {
        if (!replyTextArea.getText().trim().isEmpty()  && connectButton.isSelected()) {
            lastPost = replyTextArea.getText().trim();
            chat.send(lastPost);
            System.out.println(lastPost.length()+" "+lastPost);
            replyTextArea.setText(null);
        }
    }

    private String processPost(String s) {
        return s.replaceAll("event:insert,", "http://POST.NUM/");
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ChatGUI().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField ChatField;
    private javax.swing.JTextField HandshakeField;
    private javax.swing.JToggleButton connectButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JSplitPane jSplitPane;
    private javax.swing.JLabel onlineLabel;
    private javax.swing.JScrollPane postsScrollPane;
    private javax.swing.JTextPane postsTextPane;
    private javax.swing.JLabel radioLabel;
    private javax.swing.JPanel replyPanel;
    private javax.swing.JScrollPane replyScrollPane;
    private javax.swing.JTextArea replyTextArea;
    private javax.swing.JButton sendButton;
    // End of variables declaration//GEN-END:variables
}